package com.jy.api.service.impl;

import com.jy.api.dao.ProductDao;
import com.jy.api.dao.StockTransactionDao;
import com.jy.api.domain.*;
import com.jy.api.service.StockTransactionService;
import com.jy.api.signUpReq.stock.BarAssembleReq;
import com.jy.api.signUpReq.stock.InventoryInReq;
import com.jy.api.signUpReq.stock.StockBarReq;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.*;

/**
 * Created by lihu on 2018/2/5.
 */
@Service
@Slf4j
public class StockTransactionServiceImpl implements StockTransactionService {

    @Autowired
    StockTransactionDao stockTransactionDao;

    @Autowired
    ProductDao productDao;

    @Autowired
    private TransactionTemplate transactionTemplate;


    @Override
    public void refundStockIn(Order order) {
        log.debug("Start to record stock in data for order:{}", order.getId());
        Map<String, OrderItem> itemMap = new HashMap<>();
        List<String> list = new ArrayList<>();

        HashMap<Integer, Integer> countMap = new HashMap<>();
        List<Integer> integers = new ArrayList<>();

        for (OrderItem orderItem : order.getItems()) {
            if (null != orderItem.getProductId()) {
                list.add(orderItem.getProductId());
                itemMap.put(orderItem.getProductId(), orderItem);
            } else {
                continue;
            }
        }

        for (OrderItem orderItem : order.getItems()) {
            int count = orderItem.getQuantity();
            if (0 == orderItem.getSetMealId()) {
                continue;
            } else {
                if (countMap.containsKey(orderItem.getSetMealId())) {
                    count += 1;

                }
                integers.add(orderItem.getSetMealId());
                countMap.put(orderItem.getSetMealId(), count);
            }
        }
        if (integers.size() > 0) {
            List<StockChangeTransaction> transactions = new ArrayList<>();
            List<Product> products = productDao.findByStockEnabledAndSetMealIdInAndEnabled(true, integers, true);
            for (Product product : products) {
                if (product.isStockEnabled()) {
                    int count = countMap.get(product.getSetMealId());
                    product.setQuantity(product.getQuantity() + (product.getSetMealQty() * count));
                    /**
                     * 初始化入库记录
                     */
                    StockChangeTransaction stockTransaction = new StockChangeTransaction(order.getId(),
                            order.getCreatorId(), order.getCreatorName(), product.getSetMealQty() * count,
                            product, StockType.STOCK_IN, order.getRefundReason());
                    transactions.add(stockTransaction);
                } else {
                    continue;
                }

            }
            log.debug("stock change list size:{}", transactions.size());
            transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    productDao.save(products);
                    stockTransactionDao.save(transactions);
                }
            });
        }

        if (list.size() > 0) {
            List<StockChangeTransaction> transactions = new ArrayList<>();
            List<Product> products = productDao.findByStockEnabledAndIdIn(true, list);
            for (Product product : products) {
                if (product.isStockEnabled()) {
                    OrderItem orderItem = itemMap.get(product.getId());
                    product.setQuantity(product.getQuantity() + (orderItem.getQuantity()));
                    /**
                     * 初始化入库记录
                     */
                    StockChangeTransaction stockTransaction = new StockChangeTransaction(order.getId(),
                            order.getCreatorId(), order.getCreatorName(), orderItem.getQuantity(),
                            product, StockType.STOCK_IN, order.getRefundReason());
                    transactions.add(stockTransaction);
                } else {
                    continue;
                }

            }
            log.debug("stock change list size:{}", transactions.size());
            transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    productDao.save(products);
                    stockTransactionDao.save(transactions);
                }
            });

        }
    }


    @Override
    @Transactional
    public void addStockIn(InventoryInReq signupReq, long receiptId) {
        java.sql.Date date = new java.sql.Date(System.currentTimeMillis());
        List<StockChangeTransaction> stockInTransactions = new ArrayList<>();
        for (InventoryInReq.Inventore inventore : signupReq.getInventores()) {
            StockChangeTransaction stockTransaction = new StockChangeTransaction(inventore,
               /*店铺id*/signupReq.getStoreId(),/*入库*/ StockType.STOCK_IN,/*出入库原因*/ signupReq.getStockSource(),
                    /*操作人的id*/ signupReq.getOperatorId(), /*操作人的名字*/signupReq.getOperatorName(), String.valueOf(receiptId),/*操作人的备注*/ signupReq.getNotes(), inventore.getQuantity());
            stockTransaction.setAddTime(date);
            stockInTransactions.add(stockTransaction);
        }
        stockTransactionDao.save(stockInTransactions);
    }


    @Override
    @Transactional
    public void addStockOut(InventoryInReq inReq, long receiptId) {
        List<StockChangeTransaction> stockInTransactions = new ArrayList<>();
        for (InventoryInReq.Inventore inventore : inReq.getInventores()) {
            StockChangeTransaction stockTransaction = new StockChangeTransaction(inventore,
               /*店铺id*/inReq.getStoreId(),/*出库*/ StockType.STOCK_OUT,/*出入库原因*/ inReq.getStockSource(),
                   /*操作人的id*/ inReq.getOperatorId(), /*操作人的名字*/inReq.getOperatorName(), String.valueOf(receiptId),/*操作人的备注*/ inReq.getNotes(), inventore.getQuantity());
            stockTransaction.setAddTime(new Date());
            stockInTransactions.add(stockTransaction);
        }
        stockTransactionDao.save(stockInTransactions);
    }

    @Override
    @Transactional
    public void addBarIn(StockBarReq req) {
        List<StockChangeTransaction> stockInTransactions = new ArrayList<>();
        String s = "INNER_IN";
        for (StockBarReq.BarProduct product : req.getBarProducts()) {
            Product p = productDao.findOne(product.getProductId());
            StockChangeTransaction stockTransaction = new StockChangeTransaction(p, product, StockLevel.BAR,
               /*店铺id*/req.getStoreId(),/*出库*/ StockType.STOCK_IN,/*操作人的id*/ req.getEmpId(), /*操作人的名字*/req.getOperatorName(),/*操作人的备注*/ req.getNotes(), s);
            stockInTransactions.add(stockTransaction);
        }
        stockTransactionDao.save(stockInTransactions);
    }


    @Override
    @Transactional
    public void addBarOut(StockBarReq req) {
        List<StockChangeTransaction> stockInTransactions = new ArrayList<>();
        String s = "INNER_OUT";
        for (StockBarReq.BarProduct product : req.getBarProducts()) {
            Product p = productDao.findOne(product.getProductId());
            StockChangeTransaction stockTransaction = new StockChangeTransaction(p, product, StockLevel.BAR,
               /*店铺id*/req.getStoreId(),/*出库*/ StockType.STOCK_OUT,/*操作人的id*/ req.getEmpId(), /*操作人的名字*/req.getOperatorName(),/*操作人的备注*/ req.getNotes(), s);
            stockInTransactions.add(stockTransaction);
        }
        stockTransactionDao.save(stockInTransactions);
    }

    @Override
    public Page<StockChangeTransaction> assembleReq(BarAssembleReq req, Pageable pageable) {
        StockChangeTransaction stockChangeTransaction = new StockChangeTransaction(req);
        Example<StockChangeTransaction> example = Example.of(stockChangeTransaction);
        return stockTransactionDao.findAll(example, pageable);
    }


}
